/**
 * Copyright (c) 2008 Luciano Bustos - riaevolution.com, All Rights Reserved.
 *
 * Contact luchyx@riaevolution.com
 * See www.riaevolution.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * */
package com.riaevolution.controls.notification {
	import flash.display.DisplayObject;
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import flash.utils.setTimeout;
	
	import mx.collections.ArrayCollection;
	import mx.core.Application;
	import mx.effects.Move;
	import mx.events.CloseEvent;
	import mx.managers.PopUpManager;
	import mx.styles.StyleManager;

	/**
	 * PopUpNotifications OS style.
	 * Api support for display nice notification messages.
	 * 
	 * <br />
	 * <br />
	 * <b>Author:</b> luciano bustos<br /> 
	 * <b>Created on:</b> 05 Octubre 2010<br /> 
	 */
	public class Notification {
		/**
		 * Informational notifications
		 */
		public static const INFO:int=1;
		/**
		 * warning notifications
		 */
		public static const WARNING:int=2;


		private static var calltimes:int=0;
		/**
		 * Delay or screen time for the notifications.
		 * 8 seconds of default
		 */
		public static var DELAY:int=1000 * 8; //NO PMD

		/**
		 * Turn on|off the notifications pop display.
		 */
		public static var DISPLAY_ENABLED:Boolean=true; //NO PMD


		/**
		 * Limit of total notifications to collec in memory
		 */
		public static var limit:int=20; //NO PMD
		/**
		 * Array of notifications.
		 */
		[Bindable]
		public static var notifications:ArrayCollection; //NO PMD

		private static function hide(instance:NotificationView):void {
			if(notifications && notifications.getItemIndex(instance.data) != -1) {
				notifications.removeItemAt(notifications.getItemIndex(instance.data));
			}
			PopUpManager.removePopUp(instance);
			instance.removeEventListener(CloseEvent.CLOSE, hideSelf);
			instance.removeEventListener(MouseEvent.MOUSE_OVER, upSelf);
			calltimes--;
			if (calltimes < 1) {
				calltimes=0;
			}
			instance=null;
		}

		private static function hideSelf(event:CloseEvent):void {
			(event.currentTarget as NotificationView).removeEventListener(CloseEvent.CLOSE, hideSelf);
			hide(event.currentTarget as NotificationView);
		}
		private static function upSelf(event:MouseEvent):void {
			if((event.currentTarget as NotificationView).isPopUp) {
				PopUpManager.bringToFront(event.currentTarget as NotificationView);
			}
		}
		/**
		 * Handy method to display an info notification 
		 * @param message a message to display
		 * @param title
		 * @param config
		 */		
		public static function inform(message:String, title:String = "INFORMATION", config:Object = null):void {
			show(new Notification(title,message), config);
		}
		
		/**
		 * Handy method to display a warning notification 
		 * @param message a message to display
		 * @param title
		 * @param config
		 */
		public static function warn(message:String, title:String = "WARNING", config:Object = null):void {
			show(new Notification(title,message,2), config);
		}

		/**
		 * Display a notification Item on the application canvas.
		 *
		 * @param notification
		 * @param config an object with properties to configure the display option<br />
		 * config.position = "LT|RT|LB|BR|MOUSE",<br />
		 * config.delay = 3400,<br />
		 * config.animation = false|true<br />
		 */
		public static function show(notification:Notification, config:Object=null):void { //NO PMD

			if (notifications == null || notifications.length > limit) {
				notifications=new ArrayCollection();
			}
			//collect this notification
			notifications.addItemAt(notification,0);

			if (DISPLAY_ENABLED == false) {
				return;
			}
			//OK.
			var notifView:NotificationView=new NotificationView();
			notifView.data=notification;
			notifView.addEventListener(CloseEvent.CLOSE, hideSelf);
			notifView.addEventListener(MouseEvent.MOUSE_OVER, upSelf);

			var position:String="BR";
			var animation:Boolean=true;

			var gap:Number=4;
			var deltaX:Number=10;
			var deltaY:Number=10;

			if(config && config.position) {
				position = config.position;
			}
			if(config && config.animation) {
				animation = config.animation;
			}
			var moveEffect:Move;
			if (animation) {
				moveEffect=new Move();
			}

			switch (position) {
				default:
				case "MOUSE":
					var offset:Number = 16 * notifications.length;
					deltaX=Application.application.mouseX + gap + offset;
					deltaY=Application.application.mouseY + gap + offset;
					if (animation) {
						moveEffect.xFrom=deltaX;
						moveEffect.xTo=deltaX;
						moveEffect.yFrom=0;
						moveEffect.yTo=deltaY;
					}
				break;
				case "RB":
				case "BR":
					deltaX=Application.application.width - notifView.minWidth - gap;
					deltaY=Application.application.height - ((calltimes + 1) * (notifView.height + gap));
					notifView.x=deltaX;
					if (animation) {
						moveEffect.yFrom=Application.application.height;
						moveEffect.yTo=deltaY;
					}
					else {
						notifView.y=deltaY;
					}
					break;
			}
			PopUpManager.addPopUp(notifView, Application.application as DisplayObject);
			if (animation) {
				moveEffect.play([notifView]);
			} else {
				notifView.move(deltaX,deltaY);
			}
			setTimeout(hide, DELAY * (calltimes + 1), notifView);
			calltimes++;
		}

		/**
		 * Create a new notification DTO
		 *
		 * @param title The main title of this info item
		 * @param message A explained description.also HTML string is supported.
		 * @param type could be 1 | 2
		 */
		public function Notification(title:String, message:String, type:int=1) {
			this._title=title;
			this._message=message;
			this._type=type;
		}

		private var _type:int=1;

		/**
		 * return the notification type. warning and error
		 * @return
		 *
		 */
		public function get type():int {
			return _type;
		}

		/**
		 * Get the label
		 * @return
		 *
		 */
		public function get label():String {
			return title;
		}

		private var _title:String="";

		/**
		 * return the title of the notification.
		 *
		 * @return
		 */
		public function get title():String {
			return _title;
		}

		private var _message:String="";

		/**
		 * Return the message to display.
		 * HTML is supporte by the component.
		 * @return
		 */
		public function get message():String {
			return _message;
		}
	}
}